home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
boot
/
netBoot.new
/
sys
/
commands.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-19
|
37KB
|
1,219 lines
/*
* @(#)commands.c 1.1 86/09/27
* Copyright (c) 1986 by Sun Microsystems, Inc.
*/
/*
* commands.c: Sun ROM monitor command interpreter and execution.
*/
/*CC*************************************************************************
*CC*
*CC* 5-Dec-85 Modified the K2 command to reset all of the devices on the
*CC* main CPU board that are not reset by the CPU-RESET command
*CC* RJHG But are normally reset by a watchdog reset according to the
*CC* Sun/3 architecture manual rev 2.0
*CC* Also reset the Intel/Sun control register which is NOT reset
*CC* by the CPU-RESET command. Apperently only the Intel chips
*CC* themselves are reset.
*CC*
*CC* NOTE: The K2 command definition is altered to mean a
*CC* SOFTWARE reset of all registers/devices on the MAIN
*CC* CPU BOARD that are listed as being reset by the
*CC* watchdog or power on reset in the Sun-3 Architecture
*CC* manual version 2.0
*CC*
*CC*************************************************************************/
#include "../sun3/sunmon.h"
#include "../h/globram.h"
#include "../dev/zsreg.h"
#include "../sun3/m68vectors.h"
#include "../h/statreg.h"
#include "../sun3/cpu.addrs.h"
#include "../sun3/cpu.map.h"
#include "../h/buserr.h"
#include "../sun3/cpu.misc.h"
#include "../h/pginit.h"
#include "../h/montrap.h"
#include "../h/led.h"
#include "../h/keyboard.h"
#include "../sun3/memerr.h"
#include "../h/interreg.h"
#include "../h/clock.h"
#include "../dev/saio.h"
#include "../h/enable.h"
#include "../h/eeprom.h"
#include "../diag/diagmenus.h" /* required for struct involving the SCSI */
/* logic and reseting it with the K2 cmd */
#include "../dev/if_obie.h" /* required for struct involving the Intel */
/* ethernet logic and reseting it with the */
/* K2 cmd */
#ifdef SIRIUS
#include "../h/cache.h"
#endif SIRIUS
extern unsigned char peekchar(), getone();
char menu_msg[] = "\nOptional Menu Tests\r\nType a character within 10 seconds to enter Menu Tests...";
/*
* Opcode definitions that the monitor occasionally stuffs into memory
*/
#define OPC_TRAP1 0x4E41 /* trap 1 */
int trap(); /* Trap handler for trace and bkpt traps */
int bootreset(); /* Call it (no return) to reset and boot */
/*
* Prints and/or modifies a location. The address and length (2, 4, or 8
* hex digits) are arguments. The result is 1 if the location was modified,
* 2 if it was not, but a cr was typed, and 0 if anything else was typed.
*/
queryval(adr,len,space)
register int adr;
int len, space;
{
register unsigned char c;
register unsigned long val;
register int retval;
while (' ' == (c = peekchar())) getone();
if (ishex(c) < 0) {
/* No value was supplied. Read current value, print it, then
see if s/he wants to modify it. */
printf(": ");
switch (len) { /* Get the value from storage */
default:val = getsb(adr,space); break;
case 4: val = getsw(adr,space); break;
case 8: val = getsl(adr,space); break;
}
printhex((int)val,len);
/* Value is printed. If there's more on the line, and it's
hex, use it; else if there's nonhex, return for continuation,
else if there's nothing more on the line, quit. */
if ('\r' != c) {
getone();
while (' ' == (c = peekchar())) getone();
if (ishex(c) >= 0) goto UseIt;
putchar ('\n');
if ('\r' == c) return 0; /* Done with command */
else return 1; /* Use rest of line */
}
printf("? "); /* No arg supplied; ask for one */
getline(1);
c = peekchar();
/* CR typed here means "don't store, but continue" */
if (c == '\r') return 1; /* cr typed */
if (ishex(c) < 0) return 0;/* non-hex, non-cr */
val = getnum();
retval = 1; /* Continue after storing */
} else {
/* Value supplied on command line or with prev value --
use it, and quit if end of line, or continue if more */
UseIt:
val = getnum();
printf (" -> ");
printhex ((int)val, len);
putchar ('\n');
while (' ' == (c = peekchar())) getone();
if (c == '\r') retval = 0; /* Quit after storing */
else retval = 1; /* Continue after storing */
}
switch (len) { /* Put it back in storage */
default: putsb(adr,space,val); break;
case 4: putsw(adr,space,val); break;
case 8: putsl(adr,space,val); break;
}
/* try sending back retval for now MJC */
/*
return 2;
*/
return(retval);
}
/* Register names */
char reg_names[][3]= {
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6",
"IS", "MS", /* Two super stack pointers on '020 */
"US", "SF", "DF", "VB",
"CA", "CC", /* Cache controls on 68020 */
"CX", /* Context register */
"SR", "PC",
};
/*
* Display a register, get new value (if any)
* If right answer:increment and repeat until last reg
* Arguments are first reg (&r_d0) and first reg to print.
*/
openreg(rbase, radx)
long *rbase;
register long *radx;
{
register char (*r)[3];
radx += (getnum()&0xF); /* only use last hex digit */
r = reg_names + (radx - rbase);
for(; r < reg_names+(sizeof reg_names/sizeof *reg_names); r++, radx++) {
printf(r);
if (!queryval ((int)radx, 8, FC_SD)) break;
}
}
/* Sets up a break point in address space <space> */
dobreak(space)
int space;
{
register short *bp= gp->g_breakaddr;
register short *bpa;
if (bp && (getsw(bp,space) != OPC_TRAP1))
bp = 0;
if (peekchar() == '\r') {
printhex ( (int)bp, ADDR_LEN);
printf (" now.\n");
} else {
bpa= (short*)getnum();
if (bp) {
/* Restore user's old instruction */
putsw(bp, space, gp->g_breakval);
/* Restore supervisor's TRAP #1 routine */
(void) set_evec (EVEC_TRAP1, gp->g_breakvec);
}
if (bpa) {
/* Save new instruction */
gp->g_breakval = getsw(bpa, space);
/* Install bkpt atop new instruction */
putsw(bpa, space, OPC_TRAP1);
/* Install new TRAP #1 vector in supervisor space */
gp->g_breakvec = set_evec (EVEC_TRAP1, trap);
printf ("Break %x installed\n", gp->g_breakval);
}
gp->g_breakaddr = bpa;
};
}
struct pgmapent mainmem_pagemap = {1, PMP_ALL, VPM_MEMORY, 0, 0, 0};
/*
* This mini-monitor does only a few things:
* a <dig> open A regs
* b <filename> bootload file and start it
* c [<address>] continue [at <address>]
* d <dig> open D regs
* e <hex number> open address (as word)
* g [<address>] start (call) [at <address>]
* k reset stack [k1 maps, k2 hard reset]
* l <hex number> open address (as long)
* m <hex number> open segment map
* o <hex number> open address (as byte)
* p <hex number> open page map
* r open PC,SR,SS,US
* t [y|n|c cmd] trace yes, no, or continuous
* u [specs] use different console device[s]
* z set simple breakpoint
*/
monitor(monintstack)
struct monintstack monintstack;
/* Note: names beginning r_ are references to monintstack */
{
register char *i;
struct pgmapent pg;
register char c;
register int goadx, adx;
int (*calladx)();
struct m25_scsi_control *scsi_ctl; /* pointer to control register */
/* for SCSI interface */
/* 'm25_scsi_control' is in file */
/* diagmenus.h */
char translationsave;
register int space;
char justtooktrace = 0;
int cnt, LEN, j, k, l, adx_mod16;
int unsigned long val, va;
int change = 0;
int modified = 0;
/*
* Default address space for storage-reference commands
* depends on whether the interrupted program was in supervisor
* or user state.
*/
if (r_sr & SR_SUPERVISOR)
space = FC_SD; /* supervisor data: FC 5 */
else
space = FC_UD; /* user data: FC 1 */
if (gp->g_keybid == 3 && r_vector == EVEC_RESET) {
if (EEPROM->ee_diag.eed_keyclick == EED_KEYCLICK)
sendtokbd(KBD_CMD_CLICK); /* turn on Keybd click */
else
sendtokbd(KBD_CMD_NOCLICK); /* turn off Keybd click */
}
switch(r_vector) { /* what caused entry into monitor? */
case EVEC_TRAPE: /* "Exit to monitor" trap instruc */
initgetkey();
break;
case EVEC_KCMD: /* "K1" command */
set_leds(~L_RUNNING); /* Set LED's to normal state */
map_mainmem(); /* map in main memory */
break; /* Just reenter monitor */
case EVEC_BOOTING:
/* Call boot routine after setting up maps, etc. */
set_leds(~L_RUNNING); /* Set LED's to normal state */
BootHere:
map_mainmem(); /* map in main memory */
goadx = boot (gp->g_lineptr);
if (goadx > 0) {
r_pc = goadx; /* Boot was OK, goto loaded code */
goto ContinueTrace;
}
break; /* Then, or else, fall into monitor */
case EVEC_DOG:
if (EEPROM->ee_diag.eed_dogaction == EED_DOG_REBOOT)
k2reset(); /* Do a Power-on-Reset */
printf("\nWatchdog reset!\n");
set_leds(~L_RUNNING); /* Set LED's to normal state */
break;
case EVEC_RESET:
set_leds(~L_RUNNING); /* Set LED's to normal state */
printf ("Auto-boot in progress...\n");
gp->g_lineptr = gp->g_linebuf; /* Empty argument to boot cmd */
gp->g_linebuf[0] = 0;
goto BootHere; /* Go do the boot */
case EVEC_ABORT:
initgetkey();
printf("\nAbort");
goto PCPrint;
case EVEC_MEMERR:
printf("\nMEMORY ERROR! Status %x, DVMA-BIT %x, Context %x,",
MEMORY_ERR_BASE->mr_er, MEMORY_ERR_BASE->mr_dvma,
MEMORY_ERR_BASE->mr_cxt);
va = MEMORY_ERR_BASE->mr_vaddr;
printf("\n Vaddr: %x", va);
printf(", Paddr: ");
printhex(((getpgmap(va) << 13) + (va & 0x1FFF)), 8);
printf(", Type %d", (getpgmap(va) & 0xC000000) >> 26);
MEMORY_ERR_BASE->mr_dvma = 0; /* Reset latched interrupt */
set_enable(get_enable() | ENA_NOTBOOT | ENA_SDVMA);
*INTERRUPT_BASE &= ~IR_ENA_CLK7;
*INTERRUPT_BASE |= IR_ENA_CLK7;
j = CLOCK_BASE->clk_intrreg;
printf(" at ");
printhex( (int)r_pc, ADDR_LEN);
if (r_format == fvo_format_sixword) {
printf(", Instr=");
printhex( (int)r_instr_addr, ADDR_LEN);
putchar('\n');
}
printf("\n");
if (gp->g_loop & 0x1 != 0)
return;
case EVEC_TRAP1:
r_pc -= 2; /* back up to broken word */
BreakPrint:
printf("\nBreak ");
printhex(gp->g_breakval, 4); /* Print opcode */
justtooktrace = 1; /* Allow quick resume with CR */
goto PCPrint;
case EVEC_TRACE:
if (gp->g_breaking) {
/* this is single step past broken instruction */
if (getsw(gp->g_breakaddr, space) == gp->g_breakval) {
/* good - not bashed since we set it, so reset it */
putsw(gp->g_breakaddr, space, OPC_TRAP1);
}
if (gp->g_breaking == 1) {
/* Trace was not previously enabled. Cancel it and
resume the breakpointed program. */
r_sr &= ~SR_TRACE;
gp->g_breaking = 0;
/* Fix supervisor trace vec */
(void) set_evec (EVEC_TRACE, gp->g_breaktrvec);
return; /* return to instr after bkpt */
}
/* Trace was previously enabled. Take trace trap now. */
gp->g_breaking = 0;
}
/*
* OK, we got a trace trap, but not because we just executed
* the instruction at a breakpoint (and are tracing to put
* back the breakpoint there).
*
* If a breakpoint it set at the next instruction, pretend
* that's why we got entered. (Bkpt at loc x takes precedence
* over trace at loc x.)
*/
if ((long)gp->g_breakaddr == r_pc)
goto BreakPrint;
r_sr |= SR_TRACE; /* Assume we wanna keep tracing. */
/* This causes MOVE-to-SR, RTE, etc, to NOT stop the trace. */
/* Only a mon command will turn the trace bit off, once set */
justtooktrace = 1;
printf ("Trace ");
printhex (*(short *)r_pc, 4);
goto PCPrint;
case EVEC_BUSERR:
if (gp->g_because.be_invalid) /* Invalid Page */
printf ("Invalid Page ");
else if (gp->g_because.be_proterr) /* Protected Page */
printf ("Protection ");
else if (gp->g_because.be_timeout) /* Timeout Error */
printf ("Timeout ");
else if (gp->g_because.be_vmeberr) /* VMEbus Error */
printf ("VMEbus ");
else if (gp->g_because.be_fpaberr) /* FPA Response Error */
printf ("FPA Response ");
else if (gp->g_because.be_fpaenerr) /* FPA Enable Error */
printf ("FPA Enable ");
printf("Bus "); /* Ensure we note it's a bus err */
goto AccAddPrint;
case EVEC_ADDERR:
printf("Address ");
AccAddPrint:
printf("Error");
if (r_format == fvo_format_bus20long) printf(", long");
if (gp->g_bestack.be20_ssw.ssw20_df) {
printf(":\n Vaddr: ");
printhex(gp->g_bestack.be20_data_fault_addr,8);
printf(", Paddr: ");
va = gp->g_bestack.be20_data_fault_addr;
printhex(((getpgmap(va) << 13) + (va & 0x1FFF)), 8);
printf(", Type %d", (getpgmap(va) & 0xC000000) >> 26);
printf(", %s, FC %d, Size %d",
gp->g_bestack.be20_ssw.ssw20_rw? "Read":"Write",
gp->g_bestack.be20_ssw.ssw20_fcode,
gp->g_bestack.be20_ssw.ssw20_siz?
gp->g_bestack.be20_ssw.ssw20_siz: 4);
} else {
printf(", PC fetch");
}
PCPrint:
printf(" at ");
printhex( (int)r_pc, ADDR_LEN);
if (r_format == fvo_format_sixword) {
printf(", Instr=");
printhex( (int)r_instr_addr, ADDR_LEN);
}
putchar('\n');
break;
case EVEC_MENU_TSTS:
set_leds(~L_RUNNING); /* Set LED's to normal state */
map_mainmem(); /* map in main memory (i.e., set up the page
* map for main menu).
*/
menutests(space);
break;
case EVEC_BOOT_EXEC:
set_leds(~L_RUNNING); /* Set LED's to normal state */
printf("%s", menu_msg);
for (j = 0; j < 5; j++) {
if (mayget() != -1) {
menutests(space);
goto boot_cont; /* Then, go to monitor */
}
DELAY(1000000);
}
gp->g_lineptr = gp->g_linebuf;
*gp->g_lineptr++ = 0;
*gp->g_lineptr++ = 0;
gp->g_lineptr = gp->g_linebuf;
bootreset(); /* Boot EEPROM path */
boot_cont:
break; /* by passing command line */
default:
DeFault:
printf("\nException %x", r_vector);
if (r_format != fvo_format_short
&& r_format != fvo_format_sixword)
printf(" format %x", r_format);
goto PCPrint;
} /* end of switch(r_vector) */
r_highsr = 0; /* clear extraneous high word */
/* The following is temporarily deleted cause stack somehow
gets screwed up FIXME. mjc
*/
/* translationsave = gp->g_translation;
gp->g_translation = TR_ASCII;
*/
if (gp->g_tracecmds) {
/* Auto-execute a command after a trace trap if no keyin */
if (r_vector != EVEC_TRACE || mayget() >= 0) {
gp->g_tracecmds = 0;
} else {
gp->g_lineptr = gp->g_tracecmds;
goto TraceCont;
}
}
for (;;) {
if (gp->g_tracecmds) {
gp->g_lineptr++;
if (*gp->g_lineptr)
goto TraceCont;
if (mayget() < 0)
goto ContinueTrace;
}
/* Else get a line of input */
/* Don't prompt or input line for menu tests or
/* exec boot */
if (r_vector != EVEC_MENU_TSTS &&
r_vector != EVEC_BOOT_EXEC) {
putchar('>');
getline(1);
}
/* reset r_vector for normal Monitor prompts and input */
if (r_vector == EVEC_MENU_TSTS ||
r_vector == EVEC_BOOT_EXEC)
r_vector = EVEC_RESET;
if (justtooktrace && peekchar() == '\r')
goto ContinueTrace;
justtooktrace = 0;
TraceCont:
while(c= getone()) /* Skip control chars */
if (c >= '0')
break;
skipblanks(); /* remove any spaces before argument */
if (c == '\0')
continue;
switch(c&UPCASE) { /* slight hack, force upper case */
case 'A': /* open A register */
openreg(&r_d0, &r_a0);
goto setcontexts; /* Might have modified UC/SC */
case 'B': /* Bootload from net, disk, or whatever */
gp->g_linebuf[gp->g_linesize] = 0;
/* If first char is not '!', reset system too */
if ('!' == peekchar()) {
getone(); /* Skip the - */
r_pc = boot (gp->g_lineptr);
} else {
bootreset();
/*NOTREACHED*/
}
break;
case 'C': /* Continue */
if(ishex(peekchar()) >= 0)
r_pc = getnum();
ContinueTrace:
if ( (long)gp->g_breakaddr == r_pc) {
putsw(gp->g_breakaddr, space, gp->g_breakval);
gp->g_breaking = 1 + (r_sr & SR_TRACE);
gp->g_breaktrvec = set_evec(EVEC_TRACE, trap);
r_sr |= SR_TRACE;
}
/* deleted for the same reason mentioned above FIXME mjc
gp->g_translation = translationsave;
*/
return;
case 'D': /* open D register */
openreg(&r_d0, &r_d0);
goto setcontexts; /* Might have modified UC/SC */
case 'E': /* open memory (short word) */
for(goadx = getnum(); ;goadx+=2) {
printhex(goadx, ADDR_LEN);
if (!queryval(goadx,4,space)) break;
}
break;
case 'F': /* Fill address space with pattern */
skipblanks(); /* to next non-blank */
j = getnum();
skipblanks(); /* to next non-blank */
k = getnum();
skipblanks(); /* to next non-blank */
l = getnum();
skipblanks(); /* to next non-blank */
switch (getone() & UPCASE)
{
case 'W':
LEN = WORD_LEN;
j = j & 0xFFFFFFFE; /* make word address */
k = k & 0xFFFFFFFE;
break;
case 'L':
LEN = LONG_LEN;
j = j & 0xFFFFFFFC; /* make long address */
k = k & 0xFFFFFFFC;
break;
case 'B':
LEN = BYTE_LEN;
break;
default:
LEN = BYTE_LEN;
break;
}
for (adx = j; adx <= k; adx += (LEN/2))
{
switch (LEN)
{
case BYTE_LEN:
putsb(adx,space,l); break;
case WORD_LEN:
putsw(adx,space,l); break;
case LONG_LEN:
putsl(adx,space,l); break;
}
}
break;
case 'G': /* Go */
if (ishex (peekchar()) >= 0)
*((long*)&calladx) = getnum();
else
*((long*)&calladx) = r_pc;
gp->g_linebuf[gp->g_linesize] = 0;
skipblanks(); /* to next non-blank */
if ((int) calladx < 8) goto v_command;
(*calladx)(gp->g_lineptr);
break;
case 'H':
help();
break;
#ifdef SIRIUS
case 'I':
for (adx = getnum() + CACHEDOFF; ; adx+= CACHEDINCR) {
if (adx < CACHEDOFF ||
(adx >= CACHEDOFF
+ CACHE_SIZE)) break;
printf("CacheData ");
printhex(adx,8);
if (!queryval(adx,8,FC_MAP)) break;
}
break;
case 'J':
for (adx = getnum() + CACHETOFF; ; adx+= CACHETINCR) {
if (adx < CACHETOFF ||
(adx >= CACHETOFF
+ CACHE_SIZE)) break;
printf("CacheTags ");
printhex(adx,8);
if (!queryval(adx,8,FC_MAP)) break;
}
break;
case 'N':
skipblanks();
switch((c=getone()&UPCASE))
{
case 'I':
printf("Invalidate");
break;
case 'E':
printf("Enable");
break;
case 'D':
printf("Disable");
break;
default: break;
}
printf(" Cache\n"); /* for squeeze */
cache_dei(c); /* do the action */
break;
case 'Y': /* flush */
skipblanks();
c = getone() & UPCASE;
/* now, get num-addr */
skipblanks();
if( (adx=getnum()) < 0) break ; /* error */
/* interpret the previous 'c' */
switch(c) {
case 'C' :
vac_ctxflush(adx);
printf("Context");
break;
case 'S' :
case 'P' :
if( (goadx=getnum()) < 0) break; if( c == 'S') {
vac_segflush(adx,goadx);
printf("Segment");
}
else {
vac_pageflush(adx,goadx);
printf("Page");
}
break;
default:
/* printf("Wrong command %c\n",c); */
break;
}
printf(" flushed\n");
break; /* end 'Y' */
#endif SIRIUS
case 'K': /* reset monitor */
switch (getnum()) {
case 0: /* K0 - Reset instruction only */
resetinstr();
*INTERRUPT_BASE |= IR_ENA_INT + IR_ENA_CLK7;
/* Enable NMI */
#ifndef GRUMMAN
finit (ax, ay); /* Fix video */
#endif GRUMMAN
break;
case 1: /* K1 - Reset 'most everything */
softreset();
/*NOTREACHED*/
case 2: /* K2 - Reset just like power-up */
resetinstr();
#ifndef M25 /* this register isn't in the m25 (Sun-3/50) so we don't */
/* clear it if this is a Sun-3/50 */
ETHER_BASE->obie_noreset = 0; /* reset the */
ETHER_BASE->obie_noloop = 0; /* Intel/Sun */
ETHER_BASE->obie_ca = 0; /* ethernet */
ETHER_BASE->obie_ie = 0; /* control reg*/
#endif M25
/* reset the keyboard/mouse uart which is */
/* not reset by the CPU-RESET instruction */
/* in the k2reset code */
reset_uart(&KEYBMOUSE_BASE[0].zscc_control,1);
setfc3(sizeof(u_char),ENABLEREG,0);
/* clear SYSTEM enable reg */
setfc3(sizeof(u_char),UDMAENABLEOFF,0);
/* clear USR DVMA enable reg */
setfc3(sizeof(u_char),DIAGREG,0);
/* clear USR DVMA enable reg */
MEMORY_ERR_BASE->mr_er = 0;
/* clear memory error control */
/* ECC or PARITY memory */
#ifdef SIRIUS
/* clear ECC Diagnostic reg */
#endif SIRIUS
#ifdef M25
scsi_ctl = (struct m25_scsi_control *)
((u_int)SCSI_BASE +
M25_SCSI_CONTROL_OFFSET);
scsi_ctl->status = 0;
/* reset the 2 SCSI interface chips */
/* and the control logic */
#endif M25
k2reset();
/*NOTREACHED*/
case 0xB: /* KB - Print power-up banner only */
banner();
break;
default:
break;
}
break;
case 'L': /* open memory (long word) */
for(goadx = getnum(); ;goadx+=4) {
printhex(goadx, ADDR_LEN);
if (!queryval(goadx,8,space)) break;
}
break;
case 'M': /* open segment map entry */
for (goadx = getnum() & (ADRSPC_SIZE-1)
& ~(PGSPERSEG*BYTESPERPG-1);
goadx < ADRSPC_SIZE;
goadx += PGSPERSEG*BYTESPERPG) {
printf("SegMap ");
printhex(goadx, ADDR_LEN);
if (!queryval((int)SEGMAPADR(goadx),2,FC_MAP))
break;
}
break;
case 'O': /* open memory (byte) */
for(goadx = getnum(); ; ++goadx) {
printhex(goadx, ADDR_LEN);
if (!queryval(goadx,2,space)) break;
}
break;
case 'P': /* set page map */
for (goadx = getnum()&(ADRSPC_SIZE-1)&~(BYTESPERPG-1);
goadx < ADRSPC_SIZE;
goadx += BYTESPERPG) {
printf("PageMap ");
printhex(goadx, ADDR_LEN);
{ register segnum_t seggy;
seggy = getsegmap(goadx);
printf(" [");
printhex(seggy,2);
putchar(']');
}
if (!queryval((int)PAGEMAPADR(goadx),8,FC_MAP))
break;
}
break;
case 'Q': /* open EEPROM (byte) */
modified = 0;
for (adx = getnum() + (long int )EEPROM_BASE; ; ++adx) {
if ((adx < (long int )EEPROM_BASE) ||
(adx >= (long int )EEPROM_BASE
+ EEPROM_SIZE)) break;
printf("EEPROM ");
printhex(adx,EEPROM_LEN);
change = queryval(adx,BYTE_LEN,space);
if (!change)
break;
if (change == 2) /* EEPROM modified */
modified = 1;
}
if (modified)
eeprom_update(--adx, space);
break;
case 'R': /* open registers */
openreg(&r_d0, &r_isp);
setcontexts:
setcontext(r_context); /* Modify context reg if set */
break;
case 'S':
if (goadx = getnum()) space = goadx&7;
else printf ("FC%x space\n", space);
break;
case 'T': /* Trace: ty = on; tcxxx = on w/cmd; else off */
switch (UPCASE & getone()) {
case 'C':
{ /* Turn semis into CR's */
register unsigned char *foo;
foo = gp->g_lineptr;
gp->g_tracecmds = foo;
while (*foo) {
if (*foo++ == ';')
*--foo = '\r';
}
}
goto DoTrace;
case 'Y':
gp->g_tracecmds = 0;
DoTrace:
printf ("Tracing...\n");
r_sr |= SR_TRACE;
gp->g_tracevec = set_evec(EVEC_TRACE, trap);
goto ContinueTrace;
default:
r_sr &= ~SR_TRACE;
(void) set_evec(EVEC_TRACE, gp->g_tracevec);
printf("Trace Off\n");
}
break;
case 'U': /* Use different console I/O */
usecmd();
break;
case 'V': /* View virtual address space */
skipblanks(); /* to next non-blank */
j = getnum() & 0xFFFFFFF0;
skipblanks(); /* to next non-blank */
k = getnum() & 0xFFFFFFF0;
skipblanks(); /* to next non-blank */
switch (getone() & UPCASE)
{
case 'B': /* View in bytes */
LEN = BYTE_LEN;
cnt = 16;
break;
case 'W': /* View in words */
LEN = WORD_LEN;
cnt = 8;
break;
case 'L': /* View in longwords */
LEN = LONG_LEN;
cnt = 4;
break;
default:
LEN = BYTE_LEN;
cnt = 16;
break;
}
for (adx_mod16 = j; adx_mod16 <= k; adx_mod16 += 16)
{
printhex(adx_mod16,ADDR_LEN);
printf(": ");
for (adx = adx_mod16;
adx < adx_mod16 + 16; adx += (LEN/2))
{
switch (LEN)
{
case BYTE_LEN: /* display bytes */
val = getsb(adx,space); break;
case WORD_LEN: /* display in words */
val = getsw(adx,space); break;
case LONG_LEN: /* display in longwords */
val = getsl(adx,space); break;
}
printhex((int)val,LEN);
printf(" ");
}
printf(" ");
for (adx=adx_mod16; adx < adx_mod16 + 16;
adx += 1)
{
c = getsb(adx, space) & 0x7F;
if ((c > 0x20) && (c < 0x7F))
putchar(c);
else
putchar(0x2E);
}
printf("\n");
l = mayget();
if ((l != -1) && (l != ' ')) getchar();
if (l == ' ') break;
}
break;
case 'W': /* Vector */
*((long*)&calladx) = getnum();
gp->g_linebuf[gp->g_linesize] = 0;
skipblanks(); /* to next non-blank */
v_command:
(*gp->g_vector_cmd)((long)calladx, gp->g_lineptr);
break;
case 'X': /* Extended Tests */
if (gp->g_insource == INKEYB)
gp->g_echoinput = 0x12;
menureset();
/* Not reached */
case 'Z': /* Zap breakpoint in, 0 removes, none shows */
dobreak(space);
break;
default:
printf("What?\n");
break;
} /* end of switch(c&UPCASE) */
} /* End of loop forever */
} /* END of procedure monitor() */
/*
* Subroutine callable via ROM Vector Table which will cause the system
* to reboot using a specified (or defaulted) argument string, as if it
* had been typed by the user.
*
* Just copy the string to linbuf so it won't get trashed, and call
* bootreset() which will do all the rest.
*/
boot_me(string)
char *string;
{
gp->g_lineptr = gp->g_linebuf;
while (*gp->g_lineptr++ = *string++) ;
gp->g_lineptr = gp->g_linebuf;
bootreset(); /*NOTREACHED*/
}
/*
* Dummy handler for 'v' (vector) routine
*/
void
vector_default(addr, string)
char *addr;
char *string;
{
/* As a demonstration, use it to print strings. */
if (*string == '%')
printf(string, addr);
else
printf("Try again.\n");
}
/*
* Map all of main memory
*/
map_mainmem() {
register char *i;
struct pgmapent pg;
pg = mainmem_pagemap; /* map in main memory */
for (i = (char *)0; i < (char *)MAINMEM_MAP_SIZE; pg.pm_page++) {
setpgmap(i, pg);
i += BYTESPERPG;
}
}
/*
* Update EEPROM write count and checksum
*/
eeprom_update(adx, space)
register int *adx;
int space;
{
register unsigned char sum = 0, checksum;
register char *sum_addr, *count_addr, *eeprom_addr;
register char *start, *end;
int count, i;
/*
* Decide which EEPROM zone was modified
*/
if (adx > (int *)&(EEPROM->ee_diag.eed_nu2) &&
adx < (int *)&(EEPROM->ee_resv.eev_wrcnt[0])) {
start = (char *)&(EEPROM->ee_diag.eed_hwupdate);
end = (char *)&(EEPROM->ee_resv.eev_wrcnt[0]);
sum_addr = (char *)&(EEPROM->ee_diag.eed_chksum[0]);
count_addr = (char *)&(EEPROM->ee_diag.eed_wrcnt[0]);
} else if (adx > (int *)&(EEPROM->ee_resv.eev_nu2) &&
adx < (int *)&(EEPROM->ee_rom.eer_wrcnt[0])) {
start = (char *)&(EEPROM->ee_resv.eev_resv[0]);
end = (char *)&(EEPROM->ee_rom.eer_wrcnt[0]);
sum_addr = (char *)&(EEPROM->ee_resv.eev_chksum[0]);
count_addr = (char *)&(EEPROM->ee_resv.eev_wrcnt[0]);
} else if (adx > (int *)&(EEPROM->ee_rom.eer_nu2) &&
adx < (int *)&(EEPROM->ee_soft.ees_wrcnt[0])) {
start = (char *)&(EEPROM->ee_rom.eer_resv[0]);
end = (char *)&(EEPROM->ee_soft.ees_wrcnt[0]);
sum_addr = (char *)&(EEPROM->ee_rom.eer_chksum[0]);
count_addr = (char *)&(EEPROM->ee_rom.eer_wrcnt[0]);
} else if (adx > (int *)&(EEPROM->ee_soft.ees_nu2) &&
adx < (int *)&(EEPROM->ee_soft.ees_resv[243]) + 1) {
start = (char *)&(EEPROM->ee_soft.ees_resv[0]);
end = (char *)&(EEPROM->ee_soft.ees_resv[240]) + 1;
sum_addr = (char *)&(EEPROM->ee_soft.ees_chksum[0]);
count_addr = (char *)&(EEPROM->ee_soft.ees_wrcnt[0]);
} else {
return;
}
/*
* Calculate a new checksum for the altered area of the EEPROM
*/
for (eeprom_addr = start; eeprom_addr < end; eeprom_addr++)
sum = sum + getsb(eeprom_addr, space);
checksum = 256 - sum; /* sum of bytes + checksum = 8 bit zero */
putsb(sum_addr, space, checksum); /* Write the checksum */
/*
* Get the current write count & increment by 1
*/
count = getsb(count_addr++, space) << 8; /* Get the new count */
DELAY(10000); /* Delay for EEPROM recovery */
count += getsb(count_addr--, space, count) + 1; /* Get the new count */
/*
* Write the updated write count in all 4 locations
*/
for (i = 0; i < 4; i++){
putsb(count_addr++, space, count >> 8);/* Write the new count */
DELAY(10000); /* Delay for EEPROM recovery */
putsb(count_addr++, space, count); /* Write the new count */
DELAY(10000); /* Delay for EEPROM recovery */
}
}
menutests(space)
int space;
{
register char c;
int l;
for (;;) {
printf("\n\nExtended Test Menu: (Enter 'q' to return"); printf(" to Monitor)\n\nCmd - Test\n\n");
#ifdef M25
display_opt("ae", "Ethernet");
#else
display_opt("ie", "Ethernet");
#endif M25
display_opt("kb", "Keyboard Input");
display_opt("me", "Memory");
#ifndef GRUMMAN
display_opt("mk", "Mouse/Keyboard Ports");
#endif GRUMMAN
#ifndef M25
display_opt("mt", "TapeMaster Bootpath");
#endif M25
display_opt("rs", "Serial Ports");
display_opt("sd", "SCSI Disk Bootpath");
#ifdef M25
display_opt("si", "SCSI Interface");
#endif M25
display_opt("st", "SCSI Tape Bootpath");
#ifdef PRISM
display_opt("vm", "Video (Monochrome)");
display_opt("vc", "Video (Color)");
display_opt("ve", "Video Enable Plane");
display_opt("cm", "Color Map");
#else PRISM
#ifndef GRUMMAN
display_opt("vi", "Video");
#endif GRUMMAN
#endif PRISM
#ifndef M25
/* display_opt("xd", "Xylogics 751 Disk Bootpath"); */
display_opt("xt", "Xylogics Tape Bootpath");
display_opt("xy", "Xylogics 450/451 Disk Bootpath");
#endif M25
if ((c = get_cmd()) == 'Q')
break;
l = (int) c;
c = getone() & UPCASE;
l = (l<<8) + (int) c;
switch (l) {
#ifdef M25
case(int)'EA': /* AMD Ethernet test */
amd_ether_test(); /* execute ethernet test */
break;
#endif M25
#ifndef M25
case (int)'EI': /* Ethernet test */
ether_test(); /* execute ethernet test */
break;
#endif M25
/*
* The parameter used in call to keybd_test
* is useless. keybd_test() doesn't declare
* any passed parameters, so it's just ignored.
* keybd_test just checks gp->g_insource to
* see which device (keyboard or port A or B)
* to test.
*/
case (int)'BK': /* Keyboard test */
keybd_test(gp->g_insource);
break;
#ifndef GRUMMAN
case (int)'KM': /* Mouse\Keyboard Loopback */
ports_test(1);
break;
#endif GRUMMAN
case (int)'EM': /* Memory Tests */
memory_test(space, 0);
break;
case (int)'SR': /* Serial Ports test */
ports_test(0);
break;
case (int)'DS': /* SCSI disk bootpath test */
boot_test("sd()");
break;
#ifdef M25
case (int)'IS': /* SCSI interface test */
scsi_test();
break;
#endif M25
case (int)'TS': /* SCSI tape bootpath test */
boot_test("st()");
break;
#ifndef M25
case (int)'TM': /* Tape Master bootpath test */
boot_test("mt()");
break;
#endif M25
#ifdef PRISM
case (int)'MV': /* monochrome video test */
memory_test(space, 1);
break;
case (int)'EV': /* enable plane test */
memory_test(space, 2);
break;
case (int)'CV': /* color frame buffer test */
memory_test(space, 3);
break;
case (int)'MC': /* color map test */
memory_test(space, 4);
break;
#else PRISM
#ifndef GRUMMAN
case (int)'IV': /* Video test */
memory_test(space, 1); /* execute video test */
break;
#endif GRUMMAN
#endif PRISM
#ifndef M25
case (int)'DX': /* Xylogics 751 disk bootpath test */
boot_test("xd()");
break;
case (int)'TX': /* Xylogics tape bootpath test */
boot_test("xt()");
break;
case (int)'YX': /* Xylogics 450/451 disk bootpath test*/ boot_test("xy()");
break;
#endif M25
default: /* none of above */
printf("\nInvalid command!\n");
break;
} /* end of switch */
} /* end of for loop */
}